/**
 * Copyright (c) 2010 CWI Amsterdam and others. All rights reserved.
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     CWI Amsterdam - initial API and implementation
 *
 * $Id$
 */
package nl.cwi.arne.impl;

import java.util.Arrays;

import nl.cwi.arne.Activation;
import nl.cwi.arne.Edge;
import nl.cwi.arne.Node;
import nl.cwi.arne.NodeActivation;
import nl.cwi.arne.factory.ArnePackage;
import nl.cwi.arne.util.NodeActivationIndexConverter;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;

/**
 * @generated
 */
public class NodeActivationImpl extends MinimalEObjectImpl implements NodeActivation {
	
	/**
	 * Convenience constructor.
	 * @param node Node to be used.
	 */
	public NodeActivationImpl(Node node) {
		super();
		setNode(node);
	}
	
	/** 
	 * Set the node this transition map is used for.
	 * @generated NOT
	 * @param newNode New node to be used.
	 */
	public void setNode(Node newNode) {
		
		// Set the node:
		setNodeGen(newNode);
		
		// Initialize the data array, but ONLY if it is not set yet:
		if (data==null) {
			data = new byte[size()];
		}
		
	}
	
	/**
	 * @generated NOT
	 */
	private int size() {
		return NodeActivationIndexConverter.getIndexCount(node.getIncoming().size());
	}
	
	/**
	 * @generated NOT
	 */
	public byte getTargetLevel(boolean... resources) {
		return data[NodeActivationIndexConverter.getIndex(resources)];
	}

	/**
	 * @generated NOT
	 */
	public void setTargetLevel(byte level, boolean... resources) {
		data[NodeActivationIndexConverter.getIndex(resources)] = level;
	}
	
	/**
	 * @generated NOT
	 */
	public boolean isMonotonic() {
		boolean[] resources = new boolean[getNode().getIncoming().size()];
		Arrays.fill(resources, false);
		return isMonotonic(resources);
	}
	
	/**
	 * @generated NOT
	 */
	private boolean isMonotonic(boolean[] resources) {
		int level = getTargetLevel(resources);
		for (int i=0; i<resources.length; i++) {
			if (!resources[i]) {
				resources[i] = true;
				if (level>getTargetLevel(resources) || !isMonotonic(resources)) return false;
				resources[i] = false;
			}
		}
		return true;
	}

	/**
	 * @generated NOT
	 */
	public Activation getCopy() {
		NodeActivation copy = new NodeActivationImpl(node);
		if (data!=null) {
			copy.setData(Arrays.copyOf(data, data.length));
		}
		return copy;
	}

	/**
	 * @generated NOT
	 */
	@Override
	public String toString() {
		if (node==null || data==null) return "null";
		String result = new String();
		Edge[] incoming = node.getIncoming().toArray(new Edge[0]);
		for (int i=0; i<data.length; i++) {
			boolean[] resources = NodeActivationIndexConverter.getResources(i,incoming.length);
			String key = "";
			for (int j=0; j<resources.length; j++) {
				if (resources[j]) key = key + incoming[j].getSource().getName();
			}
			if (key.length()==0) key = "-";
			result = result + key + ":" + data[i];
			if (i<data.length-1) result = result + ", ";
		}
		return result;
	}
	
	/* ---------------------------------------------------------------- *
	 * GENERATED CODE.                                                  *
	 * Do not edit below this line. If you need to edit, move it above  *
	 * this line and change the '@generated'-tag to '@generated NOT'.   *
	 * ---------------------------------------------------------------- */
	
	/**
	 * The default value of the '{@link #getData() <em>Data</em>}' attribute.
	 * @generated
	 */
	protected static final byte[] DATA_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getData() <em>Data</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getData()
	 * @generated
	 * @ordered
	 */
	protected byte[] data = DATA_EDEFAULT;
	
	/**
	 * The cached value of the '{@link #getNode() <em>Node</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getNode()
	 * @generated
	 * @ordered
	 */
	protected Node node;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected NodeActivationImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return ArnePackage.Literals.NODE_ACTIVATION;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Node getNode() {
		if (node != null && node.eIsProxy()) {
			InternalEObject oldNode = (InternalEObject)node;
			node = (Node)eResolveProxy(oldNode);
			if (node != oldNode) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE, ArnePackage.NODE_ACTIVATION__NODE, oldNode, node));
			}
		}
		return node;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Node basicGetNode() {
		return node;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setNodeGen(Node newNode) {
		Node oldNode = node;
		node = newNode;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ArnePackage.NODE_ACTIVATION__NODE, oldNode, node));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public byte[] getData() {
		return data;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setData(byte[] newData) {
		byte[] oldData = data;
		data = newData;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ArnePackage.NODE_ACTIVATION__DATA, oldData, data));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case ArnePackage.NODE_ACTIVATION__DATA:
				return getData();
			case ArnePackage.NODE_ACTIVATION__NODE:
				if (resolve) return getNode();
				return basicGetNode();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case ArnePackage.NODE_ACTIVATION__DATA:
				setData((byte[])newValue);
				return;
			case ArnePackage.NODE_ACTIVATION__NODE:
				setNode((Node)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case ArnePackage.NODE_ACTIVATION__DATA:
				setData(DATA_EDEFAULT);
				return;
			case ArnePackage.NODE_ACTIVATION__NODE:
				setNode((Node)null);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case ArnePackage.NODE_ACTIVATION__DATA:
				return DATA_EDEFAULT == null ? data != null : !DATA_EDEFAULT.equals(data);
			case ArnePackage.NODE_ACTIVATION__NODE:
				return node != null;
		}
		return super.eIsSet(featureID);
	}

}
